package com.hcloud.libupload.http

import android.util.Log
import com.google.gson.Gson
import com.hcloud.libupload.bean.*
import com.hcloud.libupload.comom.TaskControl
import com.hcloud.libupload.excetion.UploadError
import com.hcloud.libupload.utils.AESBase64Util
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import retrofit2.HttpException
import retrofit2.Response

class RequestTask(private val taskControl: TaskControl) {

    //快传
    fun fastUpload(fastUploadReq: FastUploadReq, fastUploadCallback: (FastUploadRes) -> Unit) {
        val call = HttpClient.instance().fastService.fastUpload(
            loginkey = fastUploadReq.loginkey,
            boxId = fastUploadReq.boxId,
            requestId = fastUploadReq.requestId,
            filename = fastUploadReq.filename,
            parentPath = fastUploadReq.parentPath,
            filetype = fastUploadReq.filetype.toString(),
            size = fastUploadReq.size,
            hash = fastUploadReq.hash,
            lastmod = fastUploadReq.lastmod
        )
        taskControl.call = call
        val res = call.execute()
        processFastRes(res) {
            taskControl.call = null
            fastUploadCallback(it)
        }
    }

    //普通put
    fun commonPut(
        commonPutReq: CommonPutReq,
        requestBody: RequestBody,
        commonPutCallback: () -> Unit
    ) {
        val call = HttpClient.instance().service.commonUpload(
            uploadId = commonPutReq.uploadId,
            authorization = commonPutReq.authorization,
            name = commonPutReq.name,
            path = commonPutReq.path,
            fileType = commonPutReq.fileType.toString(),
            start = commonPutReq.start,
            length = commonPutReq.length,
            totalSize = commonPutReq.totalSize,
            hash = commonPutReq.hash,
            requestBody = requestBody,
            longitude = commonPutReq.longitude,
            latitude = commonPutReq.latitude,
            lastmod = commonPutReq.lastmod,
            url = commonPutReq.url
        )
        val res = call.execute()
        taskControl.call = call
        if (res.isSuccessful && res.code() == 201) {
            taskControl.call = null
            commonPutCallback()
        } else {
            throw HttpException(res)
        }
    }

    fun register(registerReq: RegisterReq, registerCallback: (RegisterRes) -> Unit) {
        val gson = Gson()
        val params =
            gson.toJson(registerReq)
        val aesParams: String = AESBase64Util.encrypt(params)

        Log.i("upload-sdk", "start task-----register--${params}-")

        val req = Req(aesParams)
        val jsonBody = gson.toJson(req).toRequestBody()

        val call = HttpClient.instance().service.register(reqBody = jsonBody)
        taskControl.call = call
        val res = call.execute()

        processRes(res) {
            taskControl.call = null
            val aesRes: String = AESBase64Util.decrypt(it)
            val registerRes = gson.fromJson(aesRes, RegisterRes::class.java)
            registerCallback(registerRes)
        }
    }

    fun getPart(partReq: StatusReq, statusCallback: (StatusRes) -> Unit) {

        val gson = Gson()
        val params =
            gson.toJson(partReq)
        val aesParams: String = AESBase64Util.encrypt(params)

        val req = Req(aesParams)
        val jsonBody = gson.toJson(req).toRequestBody()

        val call = HttpClient.instance().service.status(reqBody = jsonBody)

        taskControl.call = call
        val res = call.execute()

        processRes(res) {
            taskControl.call = null
            val aesRes: String = AESBase64Util.decrypt(it)
            val statusRes = gson.fromJson(aesRes, StatusRes::class.java)
            Log.d("YiLog", "json:" + aesRes)
            statusCallback(statusRes)
        }
    }

    fun putUpload(
        putReq: PutReq,
        progressBody: RequestBody,
        putCallback: () -> Unit
    ) {

        val call = HttpClient.instance().service.upload(
            uploadId = putReq.uploadId,
            partStart = putReq.partStart,
            partSize = putReq.partSize,
            requestBody = progressBody
        )

        taskControl.putCall.add(call)
        val res = call.execute()
        if (res.isSuccessful && res.code() == 201) {
            taskControl.putCall.remove(call)
            putCallback()
        } else {
            throw HttpException(res)
        }
    }

    fun complete(completeReq: CompleteReq, completeCallback: (CompleteRes) -> Unit) {

        val gson = Gson()
        val params =
            gson.toJson(completeReq)
        val aesParams: String = AESBase64Util.encrypt(params)

        val req = Req(aesParams)
        val jsonBody = gson.toJson(req).toRequestBody()

        val call = HttpClient.instance().service.complete(reqBody = jsonBody)

        taskControl.call = call
        val res = call.execute()

        processRes(res) {
            taskControl.call = null
            val aesRes: String = AESBase64Util.decrypt(it)
            val completeRes = gson.fromJson(aesRes, CompleteRes::class.java)
            completeCallback(completeRes)
        }
    }

    fun processRes(res: Response<Res>, isSuccess: (String) -> Unit) {
        if (res.isSuccessful && res.body() != null) {
            if (res.body()!!.isOk()) {
                isSuccess(res.body()!!.data)
            } else {
                throw UploadError(
                    res.body()!!.code,
                    res.body()!!.msg
                )
            }
        } else {
            throw HttpException(res)
        }
    }

    fun processFastRes(res: Response<FastUploadRes>, isSuccess: (FastUploadRes) -> Unit) {
        if (res.isSuccessful && null != res.body()) {
            var fastUploadRes = res.body()
            if (fastUploadRes!!.errcode == 0) {
                isSuccess(fastUploadRes)
            } else {
                throw UploadError(fastUploadRes!!.errcode.toString(), fastUploadRes!!.info)
            }
        } else {
            throw HttpException(res)
        }
    }
}